home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / mipsABI / examples / sup / PORT / step07 / scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  22.3 KB  |  988 lines

  1. /*
  2.  * Copyright (c) 1992 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  12.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  13.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  14.  *
  15.  * Carnegie Mellon requests users of this software to return to
  16.  *
  17.  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
  18.  *  School of Computer Science
  19.  *  Carnegie Mellon University
  20.  *  Pittsburgh PA 15213-3890
  21.  *
  22.  * any improvements or extensions that they make and grant Carnegie Mellon
  23.  * the rights to redistribute these changes.
  24.  */
  25. /*
  26.  * scan.c - sup list file scanner
  27.  *
  28.  **********************************************************************
  29.  * HISTORY
  30.  * $Log: scan.c,v $
  31.  * Revision 1.1.1.1  1993/05/21  14:52:17  cgd
  32.  * initial import of CMU's SUP to NetBSD
  33.  *
  34.  * Revision 1.8  92/08/11  12:04:28  mrt
  35.  *     Brad's changes: delinted, added forward declarations of static
  36.  *     functions.Added Copyright.
  37.  *     [92/07/24            mrt]
  38.  * 
  39.  * 18-Mar-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
  40.  *    Added host=<hostfile> support to releases file.
  41.  *
  42.  * 11-Mar-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
  43.  *    Added "rsymlink" recursive symbolic link quoting directive.
  44.  *
  45.  * 28-Jun-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  46.  *    Added code for "release" support.
  47.  *
  48.  * 26-May-87  Doug Philips (dwp) at Carnegie-Mellon University
  49.  *    Lets see if we'll be able to write the scan file BEFORE
  50.  *    we collect the data for it.  Include sys/file.h and use
  51.  *    new definitions for access check codes.
  52.  *
  53.  * 20-May-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  54.  *    Added type casting information for lint.
  55.  *
  56.  * 21-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  57.  *    Added check for newonly upgrade when lasttime is the same as
  58.  *    scantime.  This will save us the trouble of parsing the scanfile
  59.  *    when the client has successfully received everything in the
  60.  *    scanfile already.
  61.  *
  62.  * 16-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  63.  *    Clear Texec pointers in execT so that Tfree of execT will not
  64.  *    free command trees associated with files in listT.
  65.  *
  66.  * 06-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  67.  *    Added code to omit scanned files from list if we want new files
  68.  *    only and they are old.
  69.  *
  70.  * 29-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  71.  *    Major rewrite for protocol version 4.  Added version numbers to
  72.  *    scan file.  Also added mode of file in addition to flags.
  73.  *    Execute commands are now immediately after file information.
  74.  *
  75.  * 13-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  76.  *    Added comments to list file format.
  77.  *
  78.  * 08-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  79.  *    Added code to implement omitany.  Currently doesn't know about
  80.  *    {a,b,c} patterns.
  81.  *
  82.  * 07-Oct-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  83.  *    Created.
  84.  *
  85.  **********************************************************************
  86.  */
  87.  
  88. #include <libc.h>
  89. #include <c.h>
  90. #include <sys/types.h>
  91. #include <sys/time.h>
  92. #include <sys/stat.h>
  93. #ifdef _ABI_SOURCE
  94. #include <dirent.h>
  95. #else
  96. #include <sys/dir.h>
  97. #endif
  98. #include <sys/file.h>
  99. #ifdef _ABI_SOURCE
  100. #include <utime.h>
  101. #endif
  102. #include "sup.h"
  103.  
  104. /*************************
  105.  ***    M A C R O S    ***
  106.  *************************/
  107.  
  108. #define SPECNUMBER 1000
  109.     /* number of filenames produced by a single spec in the list file */
  110.  
  111. /*******************************************
  112.  ***    D A T A   S T R U C T U R E S    ***
  113.  *******************************************/
  114.  
  115. typedef enum {            /* release options */
  116.     ONEXT,        OPREFIX,    OLIST,        OSCAN,
  117.     OHOST
  118. } OPTION;
  119.  
  120. static char *options[] = {
  121.     "next",        "prefix",    "list",        "scan",
  122.     "host",
  123.     0
  124. };
  125.  
  126. typedef enum {            /* <collection>/list file lines */
  127.     LUPGRADE,    LOMIT,        LBACKUP,    LEXECUTE,
  128.     LINCLUDE,    LNOACCT,    LOMITANY,    LALWAYS,
  129.     LSYMLINK,    LRSYMLINK
  130. } LISTTYPE;
  131.  
  132. static char *ltname[] = {
  133.     "upgrade",    "omit",        "backup",    "execute",
  134.     "include",    "noaccount",    "omitany",    "always",
  135.     "symlink",    "rsymlink",
  136.     0
  137. };
  138.  
  139. #define FALWAYS        FUPDATE
  140.  
  141. /* list file lines */
  142. static TREE *upgT;            /* files to upgrade */
  143. static TREE *flagsT;            /* special flags: BACKUP NOACCT */
  144. static TREE *omitT;            /* recursize file omition list */
  145. static TREE *omanyT;            /* non-recursize file omition list */
  146. static TREE *symT;            /* symbolic links to quote */
  147. static TREE *rsymT;            /* recursive symbolic links to quote */
  148. static TREE *execT;            /* execute command list */
  149.  
  150. /*************************
  151.  ***    E X T E R N    ***
  152.  *************************/
  153.  
  154. #ifdef    lint
  155. static char _argbreak;
  156. #else
  157. extern char _argbreak;            /* break character from nxtarg */
  158. #endif
  159.  
  160. extern TREELIST *listTL;        /* list of trees for scanning */
  161. extern TREE *listT;            /* final list of files in collection */
  162. extern TREE *refuseT;            /* files refused by client */
  163.  
  164. extern char *collname;            /* collection name */
  165. extern char *basedir;            /* base directory name */
  166. extern char *prefix;            /* collection pathname prefix */
  167. extern long lasttime;            /* time of last upgrade */
  168. extern long scantime;            /* time of this scan */
  169. extern int trace;            /* trace directories */
  170. extern int newonly;            /* new files only */
  171.  
  172. extern long time();
  173.  
  174. /*************************************************
  175.  ***   STATIC   R O U T I N E S    ***
  176.  *************************************************/
  177.  
  178. static makescan();
  179. static getscan();
  180. static doscan();
  181. static readlistfile();
  182. static expTinsert();
  183. static listone();
  184. static listentry();
  185. static listname();
  186. static listdir();
  187. static omitanyone();
  188. static anyglob();
  189. static int getscanfile();
  190. static chkscanfile();
  191. static makescanfile();
  192. static recordone();
  193. static recordexec();
  194.  
  195. /*************************************************
  196.  ***    L I S T   S C A N   R O U T I N E S    ***
  197.  *************************************************/
  198.  
  199. static
  200. passdelim (ptr,delim)        /* skip over delimiter */
  201. char **ptr,delim;
  202. {
  203.     *ptr = skipover (*ptr, " \t");
  204.     if (_argbreak != delim && **ptr == delim) {
  205.         (*ptr)++;
  206.         *ptr = skipover (*ptr, " \t");
  207.     }
  208. }
  209.  
  210. static
  211. char *parserelease(tlp,relname,args)
  212. TREELIST **tlp;
  213. char *relname,*args;
  214. {
  215.     register TREELIST *tl;
  216.     register char *arg;
  217.     register OPTION option;
  218.     int opno;
  219.     char *nextrel;
  220.  
  221.     tl = (TREELIST *) malloc (sizeof(TREELIST));
  222.     if ((*tlp = tl) == NULL)
  223.         goaway ("Couldn't allocate TREELIST");
  224.     tl->TLnext = NULL;
  225.     tl->TLname = salloc (relname);
  226.     tl->TLprefix = NULL;
  227.     tl->TLlist = NULL;
  228.     tl->TLscan = NULL;
  229.     tl->TLhost = NULL;
  230.     nextrel = NULL;
  231.     args = skipover (args," \t");
  232.     while (*(arg=nxtarg(&args," \t="))) {
  233.         for (opno = 0; options[opno] != NULL; opno++)
  234.             if (strcmp (arg,options[opno]) == 0)
  235.                 break;
  236.         if (options[opno] == NULL)
  237.             goaway ("Invalid release option %s for release %s",
  238.                 arg,relname);
  239.         option = (OPTION) opno;
  240.         switch (option) {
  241.         case ONEXT:
  242.             passdelim (&args,'=');
  243.             arg = nxtarg (&args," \t");
  244.             nextrel = salloc (arg);
  245.             break;
  246.         case OPREFIX:
  247.             passdelim (&args,'=');
  248.             arg = nxtarg (&args," \t");
  249.             tl->TLprefix = salloc (arg);
  250.             break;
  251.         case OLIST:
  252.             passdelim (&args,'=');
  253.             arg = nxtarg (&args," \t");
  254.             tl->TLlist = salloc (arg);
  255.             break;
  256.         case OSCAN:
  257.             passdelim (&args,'=');
  258.             arg = nxtarg (&args," \t");
  259.             tl->TLscan = salloc (arg);
  260.             break;
  261.         case OHOST:
  262.             passdelim (&args,'=');
  263.             arg = nxtarg (&args," \t");
  264.             tl->TLhost = salloc (arg);
  265.             break;
  266.         }
  267.     }
  268.     return (nextrel);
  269. }
  270.  
  271. getrelease (release)
  272. char *release;
  273. {
  274.     TREELIST *tl;
  275.     char buf[STRINGLENGTH];
  276.     char *p,*q;
  277.     int rewound;
  278.     FILE *f;
  279.  
  280.     if (release == NULL)
  281.         release = salloc (DEFRELEASE);
  282.     listTL = NULL;
  283.  
  284.     (void) sprintf (buf,FILERELEASES,collname);
  285.     f = fopen (buf,"r");
  286.     if (f != NULL) {
  287.         rewound = TRUE;
  288.         for (;;) {
  289.             p = fgets (buf,STRINGLENGTH,f);
  290.             if (p == NULL) {
  291.                 if (rewound)
  292.                     break;
  293.                 rewind (f);
  294.                 rewound = TRUE;
  295.                 continue;
  296.             }
  297.             q = index (p,'\n');
  298.             if (q)  *q = 0;
  299.             if (index ("#;:",*p))  continue;
  300.             q = nxtarg (&p," \t");
  301.             if (strcmp (q,release) != 0)
  302.                 continue;
  303.             release = parserelease (&tl,release,p);
  304.             if (tl->TLprefix == NULL)
  305.                 tl->TLprefix = prefix;
  306.             else if (chdir (tl->TLprefix) < 0)
  307.                 return (FALSE);
  308.             else
  309.                 (void) chdir (basedir);
  310.             tl->TLnext = listTL;
  311.             listTL = tl;
  312.             if (release == NULL)
  313.                 break;
  314.             rewound = FALSE;
  315.         }
  316.         (void) fclose (f);
  317.     }
  318.     if (release == NULL)
  319.         return (TRUE);
  320.     if (strcmp (release,DEFRELEASE) != 0)
  321.         return (FALSE);
  322.     (void) parserelease (&tl,release,"");
  323.     tl->TLprefix = prefix;
  324.     tl->TLnext = listTL;
  325.     listTL = tl;
  326.     return (TRUE);
  327. }
  328.  
  329. makescanlists ()
  330. {
  331.     TREELIST *tl;
  332.     char buf[STRINGLENGTH];
  333.     char *p,*q;
  334.     FILE *f;
  335.     char *saveprefix = prefix;
  336.     int count = 0;
  337.  
  338.     (void) sprintf (buf,FILERELEASES,collname);
  339.     f = fopen (buf,"r");
  340.     if (f != NULL) {
  341.         while (p = fgets (buf,STRINGLENGTH,f)) {
  342.             q = index (p,'\n');
  343.             if (q)  *q = 0;
  344.             if (index ("#;:",*p))  continue;
  345.             q = nxtarg (&p," \t");
  346.             (void) parserelease (&tl,q,p);
  347.             if ((prefix = tl->TLprefix) == NULL)
  348.                 prefix = saveprefix;
  349.             if (prefix != NULL) {
  350.                 if (chdir (prefix) < 0)
  351.                     goaway ("Can't chdir to %s",prefix);
  352.                 (void) chdir (basedir);
  353.             }
  354.             makescan (tl->TLlist,tl->TLscan);
  355.             free ((char *)tl);
  356.             count++;
  357.         }
  358.         (void) fclose (f);
  359.     }
  360.     if (count == 0)
  361.         makescan ((char *)NULL,(char *)NULL);
  362. }
  363.  
  364. static
  365. scanone (t)
  366. register TREE *t;
  367. {
  368.     register TREE *newt;
  369.  
  370.     if (newonly && (t->Tflags&FNEW) == 0)
  371.         return (SCMOK);
  372.     newt = Tinsert (&listT,t->Tname,FALSE);
  373.     if (newt == NULL)
  374.         return (SCMOK);
  375.     newt->Tmode = t->Tmode;
  376.     newt->Tflags = t->Tflags;
  377.     newt->Tmtime = t->Tmtime;
  378.     return (SCMOK);
  379. }
  380.  
  381. getscanlists ()
  382. {
  383.     TREELIST *tl,*stl;
  384.  
  385.     stl = listTL;
  386.     listTL = NULL;
  387.     while ((tl = stl) != NULL) {
  388.         prefix = tl->TLprefix;
  389.         getscan (tl->TLlist,tl->TLscan);
  390.         tl->TLtree = listT;
  391.         stl = tl->TLnext;
  392.         tl->TLnext = listTL;
  393.         listTL = tl;
  394.     }
  395.     listT = NULL;
  396.     for (tl = listTL; tl != NULL; tl = tl->TLnext)
  397.         (void) Tprocess (tl->TLtree,scanone);
  398. }
  399.  
  400. static
  401. makescan (listfile,scanfile)
  402. char *listfile,*scanfile;
  403. {
  404.     listT = NULL;
  405.     chkscanfile (scanfile);        /* can we can write a scan file? */
  406.     doscan (listfile);        /* read list file and scan disk */
  407.     makescanfile (scanfile);    /* record names in scan file */
  408.     Tfree (&listT);            /* free file list tree */
  409. }
  410.  
  411. static
  412. getscan (listfile,scanfile)
  413. char *listfile,*scanfile;
  414. {
  415.     listT = NULL;
  416.     if (!getscanfile(scanfile)) {    /* check for pre-scanned file list */
  417.         scantime = time ((long *)NULL);
  418.         doscan (listfile);    /* read list file and scan disk */
  419.     }
  420. }
  421.  
  422. static
  423. doscan (listfile)
  424.     char *listfile;
  425. {
  426.     char buf[STRINGLENGTH];
  427.     int listone ();
  428.  
  429.     upgT = NULL;
  430.     flagsT = NULL;
  431.     omitT = NULL;
  432.     omanyT = NULL;
  433.     execT = NULL;
  434.     symT = NULL;
  435.     rsymT = NULL;
  436.     if (listfile == NULL)
  437.         listfile = FILELISTDEF;
  438.     (void) sprintf (buf,FILELIST,collname,listfile);
  439.     readlistfile (buf);        /* get contents of list file */
  440.     (void) Tprocess (upgT,listone); /* build list of files specified */
  441.     cdprefix ((char *)NULL);
  442.     Tfree (&upgT);
  443.     Tfree (&flagsT);
  444.     Tfree (&omitT);
  445.     Tfree (&omanyT);
  446.     Tfree (&execT);
  447.     Tfree (&symT);
  448.     Tfree (&rsymT);
  449. }
  450.  
  451. static
  452. readlistfile (fname)
  453. char *fname;
  454. {
  455.     char buf[STRINGLENGTH],*p;
  456.     register char *q,*r;
  457.     register FILE *f;
  458.     register int ltn,n,i,flags;
  459.     register TREE **t;
  460.     register LISTTYPE lt;
  461.     char *speclist[SPECNUMBER];
  462.  
  463.     f = fopen (fname,"r");
  464.     if (f == NULL)  goaway ("Can't read list file %s",fname);
  465.     cdprefix (prefix);
  466.     while (p = fgets (buf,STRINGLENGTH,f)) {
  467.         if (q = index (p,'\n'))  *q = '\0';
  468.         if (index ("#;:",*p))  continue;
  469.         q = nxtarg (&p," \t");
  470.         if (*q == '\0') continue;
  471.         for (ltn = 0; ltname[ltn] && strcmp(q,ltname[ltn]) != 0; ltn++);
  472.         if (ltname[ltn] == NULL)
  473.             goaway ("Invalid list file keyword %s",q);
  474.         lt = (LISTTYPE) ltn;
  475.         flags = 0;
  476.         switch (lt) {
  477.         case LUPGRADE:
  478.             t = &upgT;
  479.             break;
  480.         case LBACKUP:
  481.             t = &flagsT;
  482.             flags = FBACKUP;
  483.             break;
  484.         case LNOACCT:
  485.             t = &flagsT;
  486.             flags = FNOACCT;
  487.             break;
  488.         case LSYMLINK:
  489.             t = &symT;
  490.             break;
  491.         case LRSYMLINK:
  492.             t = &rsymT;
  493.             break;
  494.         case LOMIT:
  495.             t = &omitT;
  496.             break;
  497.         case LOMITANY:
  498.             t = &omanyT;
  499.             break;
  500.         case LALWAYS:
  501.             t = &upgT;
  502.             flags = FALWAYS;
  503.             break;
  504.         case LINCLUDE:
  505.             while (*(q=nxtarg(&p," \t"))) {
  506.                 cdprefix ((char *)NULL);
  507.                 n = expand (q,speclist,SPECNUMBER);
  508.                 for (i = 0; i < n && i < SPECNUMBER; i++) {
  509.                     readlistfile (speclist[i]);
  510.                     cdprefix ((char *)NULL);
  511.                     free (speclist[i]);
  512.                 }
  513.                 cdprefix (prefix);
  514.             }
  515.             continue;
  516.         case LEXECUTE:
  517.             r = p = q = skipover (p," \t");
  518.             do {
  519.                 q = p = skipto (p," \t(");
  520.                 p = skipover (p," \t");
  521.             } while (*p != '(' && *p != '\0');
  522.             if (*p++ == '(') {
  523.                 *q = '\0';
  524.                 do {
  525.                     q = nxtarg (&p," \t)");
  526.                     if (*q == 0)
  527.                         _argbreak = ')';
  528.                     else
  529.                         expTinsert (q,&execT,0,r);
  530.                 } while (_argbreak != ')');
  531.                 continue;
  532.             }
  533.             /* fall through */
  534.         default:
  535.             goaway ("Error in handling list file keyword %d",ltn);
  536.         }
  537.         while (*(q=nxtarg(&p," \t"))) {
  538.             if (lt == LOMITANY)
  539.                 (void) Tinsert (t,q,FALSE);
  540.             else
  541.                 expTinsert (q,t,flags,(char *)NULL);
  542.         }
  543.     }
  544.     (void) fclose (f);
  545. }
  546.  
  547. static
  548. expTinsert (p,t,flags,exec)
  549. char *p;
  550. TREE **t;
  551. int flags;
  552. char *exec;
  553. {
  554.     register int n, i;
  555.     register TREE *newt;
  556.     char *speclist[SPECNUMBER];
  557.     char buf[STRINGLENGTH];
  558.  
  559.     n = expand (p,speclist,SPECNUMBER);
  560.     for (i = 0; i < n && i < SPECNUMBER; i++) {
  561.         newt = Tinsert (t,speclist[i],TRUE);
  562.         newt->Tflags |= flags;
  563.         if (exec) {
  564.             (void) sprintf (buf,exec,speclist[i]);
  565.             (void) Tinsert (&newt->Texec,buf,FALSE);
  566.         }
  567.         free (speclist[i]);
  568.     }
  569. }
  570.  
  571. static
  572. listone (t)        /* expand and add one name from upgrade list */
  573. TREE *t;
  574. {
  575.     listentry(t->Tname,t->Tname,(char *)NULL,(t->Tflags&FALWAYS) != 0);
  576.     return (SCMOK);
  577. }
  578.  
  579. static
  580. listentry(name,fullname,updir,always)
  581. register char *name, *fullname, *updir;
  582. int always;
  583. {
  584.     struct stat statbuf;
  585.     int link = 0;
  586.     int omitanyone ();
  587.  
  588.     if (Tlookup (refuseT,fullname))  return;
  589.     if (!always) {
  590.         if (Tsearch (omitT,fullname))  return;
  591.         if (Tprocess (omanyT,omitanyone,fullname) != SCMOK)
  592.             return;
  593.     }
  594.     if (lstat(name,&statbuf) < 0)
  595.         return;
  596.     if ((statbuf.st_mode&S_IFMT) == S_IFLNK) {
  597.         if (Tsearch (symT,fullname)) {
  598.             listname (fullname,&statbuf);
  599.             return;
  600.         }
  601.         if (Tlookup (rsymT,fullname)) {
  602.             listname (fullname,&statbuf);
  603.             return;
  604.         }
  605.         if (updir) link++;
  606.         if (stat(name,&statbuf) < 0) return;
  607.     }
  608.     if ((statbuf.st_mode&S_IFMT) == S_IFDIR) {
  609.         if (access(name,R_OK|X_OK) < 0) return;
  610.         if (chdir(name) < 0) return;
  611.         listname (fullname,&statbuf);
  612.         if (trace) {
  613.             printf ("Scanning directory %s\n",fullname);
  614.             (void) fflush (stdout);
  615.         }
  616.         listdir (fullname,always);
  617.         if (updir == 0 || link) {
  618.             (void) chdir (basedir);
  619.             if (prefix) (void) chdir (prefix);
  620.             if (updir && *updir) (void) chdir (updir);
  621.         } else
  622.             (void) chdir ("..");
  623.         return;
  624.     }
  625.     if (access(name,R_OK) < 0) return;
  626.     listname (fullname,&statbuf);
  627. }
  628.  
  629. static
  630. listname (name,st)
  631. register char *name;
  632. register struct stat *st;
  633. {
  634.     register TREE *t,*ts;
  635.     register int new;
  636.     register TREELIST *tl;
  637.  
  638.     new = st->st_ctime > lasttime;
  639.     if (newonly && !new) {
  640.         for (tl = listTL; tl != NULL; tl = tl->TLnext)
  641.             if (ts = Tsearch (tl->TLtree,name))
  642.                 ts->Tflags &= ~FNEW;
  643.         return;
  644.     }
  645.     t = Tinsert (&listT,name,FALSE);
  646.     if (t == NULL)  return;
  647.     t->Tmode = st->st_mode;
  648.     t->Tctime = st->st_ctime;
  649.     t->Tmtime = st->st_mtime;
  650.     if (new)  t->Tflags |= FNEW;
  651.     if (ts = Tsearch (flagsT,name))
  652.         t->Tflags |= ts->Tflags;
  653.     if (ts = Tsearch (execT,name)) {
  654.         t->Texec = ts->Texec;
  655.         ts->Texec = NULL;
  656.     }
  657. }
  658.  
  659. static
  660. listdir (name,always)        /* expand directory */
  661. char *name;
  662. int always;
  663. {
  664. #ifdef _ABI_SOURCE
  665.     struct dirent *dentry;
  666. #else
  667.     struct direct *dentry;
  668. #endif
  669.     register DIR *dirp;
  670.     char ename[STRINGLENGTH],newname[STRINGLENGTH],filename[STRINGLENGTH];
  671.     register char *p,*newp;
  672.     register int i;
  673.  
  674.     dirp = opendir (".");
  675.     if (dirp == 0) return;    /* unreadable: probably protected */
  676.  
  677.     p = name;        /* punt leading ./ and trailing / */
  678.     newp = newname;
  679.     if (p[0] == '.' && p[1] == '/') {
  680.         p += 2;
  681.         while (*p == '/') p++;
  682.     }
  683.     while (*newp++ = *p++) ;    /* copy string */
  684.     --newp;                /* trailing null */
  685.     while (newp > newname && newp[-1] == '/') --newp; /* trailing / */
  686.     *newp = 0;
  687.     if (strcmp (newname,".") == 0) newname[0] = 0;    /* "." ==> "" */
  688.  
  689.     while (dentry=readdir(dirp)) {
  690.         if (dentry->d_ino == 0) continue;
  691.         if (strcmp(dentry->d_name,".") == 0) continue;
  692.         if (strcmp(dentry->d_name,"..") == 0) continue;
  693.         for (i=0; i<=MAXNAMLEN && dentry->d_name[i]; i++)
  694.             ename[i] = dentry->d_name[i];
  695.         ename[i] = 0;
  696.         if (*newname)
  697.             (void) sprintf (filename,"%s/%s",newname,ename);
  698.         else
  699.             (void) strcpy (filename,ename);
  700.         listentry(ename,filename,newname,always);
  701.     }
  702.     closedir (dirp);
  703. }
  704.  
  705. static
  706. omitanyone (t,filename)
  707. TREE *t;
  708. char **filename;
  709. {
  710.     if (anyglob (t->Tname,*filename))
  711.         return (SCMERR);
  712.     return (SCMOK);
  713. }
  714.  
  715. static
  716. anyglob (pattern,match)
  717. char *pattern,*match;
  718. {
  719.     register char *p,*m;
  720.     register char *pb,*pe;
  721.  
  722.     p = pattern; 
  723.     m = match;
  724.     while (*m && *p == *m ) { 
  725.         p++; 
  726.         m++; 
  727.     }
  728.     if (*p == '\0' && *m == '\0')
  729.         return (TRUE);
  730.     switch (*p++) {
  731.     case '*':
  732.         for (;;) {
  733.             if (*p == '\0')
  734.                 return (TRUE);
  735.             if (*m == '\0')
  736.                 return (*p == '\0');
  737.             if (anyglob (p,++m))
  738.                 return (TRUE);
  739.         }
  740.     case '?':
  741.         return (anyglob (p,++m));
  742.     case '[':
  743.         pb = p;
  744.         while (*(++p) != ']')
  745.             if (*p == '\0')
  746.                 return (FALSE);
  747.         pe = p;
  748.         for (p = pb + 1; p != pe; p++) {
  749.             switch (*p) {
  750.             case '-':
  751.                 if (p == pb && *m == '-') {
  752.                     p = pe + 1;
  753.                     return (anyglob (p,++m));
  754.                 }
  755.                 if (p == pb)
  756.                     continue;
  757.                 if ((p + 1) == pe)
  758.                     return (FALSE);
  759.                 if (*m > *(p - 1) &&
  760.                     *m <= *(p + 1)) {
  761.                     p = pe + 1;
  762.                     return (anyglob (p,++m));
  763.                 }
  764.                 continue;
  765.             default:
  766.                 if (*m == *p) {
  767.                     p = pe + 1;
  768.                     return (anyglob (p,++m));
  769.                 }
  770.             }
  771.         }
  772.         return (FALSE);
  773.     default:
  774.         return (FALSE);
  775.     }
  776. }
  777.  
  778. /*****************************************
  779.  ***    R E A D   S C A N   F I L E    ***
  780.  *****************************************/
  781.  
  782. static
  783. int getscanfile (scanfile)
  784. char *scanfile;
  785. {
  786.     char buf[STRINGLENGTH];
  787.     struct stat sbuf;
  788.     register FILE *f;
  789.     TREE ts;
  790.     register char *p,*q;
  791.     register TREE *tmp, *t = NULL;
  792.     register notwanted;
  793.     register TREELIST *tl;
  794.  
  795.     if (scanfile == NULL)
  796.         scanfile = FILESCANDEF;
  797.     (void) sprintf (buf,FILESCAN,collname,scanfile);
  798.     if (stat(buf,&sbuf) < 0)
  799.         return (FALSE);
  800.     if ((f = fopen (buf,"r")) == NULL)
  801.         return (FALSE);
  802.     if ((p = fgets (buf,STRINGLENGTH,f)) == NULL) {
  803.         (void) fclose (f);
  804.         return (FALSE);
  805.     }
  806.     if (q = index (p,'\n'))  *q = '\0';
  807.     if (*p++ != 'V') {
  808.         (void) fclose (f);
  809.         return (FALSE);
  810.     }
  811.     if (atoi (p) != SCANVERSION) {
  812.         (void) fclose (f);
  813.         return (FALSE);
  814.     }
  815.     scantime = sbuf.st_mtime;    /* upgrade time is time of supscan,
  816.                      * i.e. time of creation of scanfile */
  817.     if (newonly && scantime == lasttime) {
  818.         (void) fclose (f);
  819.         return (TRUE);
  820.     }
  821.     notwanted = FALSE;
  822.     while (p = fgets (buf,STRINGLENGTH,f)) {
  823.         q = index (p,'\n');
  824.         if (q)  *q = 0;
  825.         ts.Tflags = 0;
  826.         if (*p == 'X') {
  827.             if (notwanted)  continue;
  828.             if (t == NULL)
  829.                 goaway ("scanfile format inconsistant");
  830.             (void) Tinsert (&t->Texec,++p,FALSE);
  831.             continue;
  832.         }
  833.         notwanted = FALSE;
  834.         if (*p == 'B') {
  835.             p++;
  836.             ts.Tflags |= FBACKUP;
  837.         }
  838.         if (*p == 'N') {
  839.             p++;
  840.             ts.Tflags |= FNOACCT;
  841.         }
  842.         if ((q = index (p,' ')) == NULL)
  843.             goaway ("scanfile format inconsistant");
  844.         *q++ = '\0';
  845.         ts.Tmode = atoo (p);
  846.         p = q;
  847.         if ((q = index (p,' ')) == NULL)
  848.             goaway ("scanfile format inconsistant");
  849.         *q++ = '\0';
  850.         ts.Tctime = atoi (p);
  851.         p = q;
  852.         if ((q = index (p,' ')) == NULL)
  853.             goaway ("scanfile format inconsistant");
  854.         *q++ = 0;
  855.         ts.Tmtime = atoi (p);
  856.         if (ts.Tctime > lasttime)
  857.             ts.Tflags |= FNEW;
  858.         else if (newonly) {
  859.             for (tl = listTL; tl != NULL; tl = tl->TLnext)
  860.                 if (tmp = Tsearch (tl->TLtree,q))
  861.                     tmp->Tflags &= ~FNEW;
  862.             notwanted = TRUE;
  863.             continue;
  864.         }
  865.         if (Tlookup (refuseT,q)) {
  866.             notwanted = TRUE;
  867.             continue;
  868.         }
  869.         t = Tinsert (&listT,q,TRUE);
  870.         t->Tmode = ts.Tmode;
  871.         t->Tflags = ts.Tflags;
  872.         t->Tctime = ts.Tctime;
  873.         t->Tmtime = ts.Tmtime;
  874.     }
  875.     (void) fclose (f);
  876.     return (TRUE);
  877. }
  878.  
  879. /*******************************************
  880.  ***    W R I T E   S C A N   F I L E    ***
  881.  *******************************************/
  882.  
  883. static chkscanfile (scanfile)
  884. char *scanfile;
  885. {
  886.     char tname[STRINGLENGTH], fname[STRINGLENGTH];
  887.     FILE *f;
  888.  
  889.     if (scanfile == NULL)
  890.         scanfile = FILESCANDEF;
  891.     (void) sprintf (fname,FILESCAN,collname,scanfile);
  892.     (void) sprintf (tname,"%s.temp",fname);
  893.     if (NULL == (f = fopen (tname, "w")))
  894.         goaway ("Can't test scan file temp %s for %s",tname,collname);
  895.     else {
  896.         (void) unlink (tname);
  897.         (void) fclose (f);
  898.     }
  899. }
  900.  
  901. static makescanfile (scanfile)
  902. char *scanfile;
  903. {
  904.     char tname[STRINGLENGTH],fname[STRINGLENGTH];
  905. #ifdef _ABI_SOURCE
  906.     struct utimbuf tbuf;
  907. #else
  908.     struct timeval tbuf[2];
  909. #endif
  910.     FILE *scanF;            /* output file for scanned file list */
  911.     int recordone ();
  912.  
  913.     if (scanfile == NULL)
  914.         scanfile = FILESCANDEF;
  915.     (void) sprintf (fname,FILESCAN,collname,scanfile);
  916.     (void) sprintf (tname,"%s.temp",fname);
  917.     scanF = fopen (tname,"w");
  918.     if (scanF == NULL)
  919.         goaway ("Can't write scan file temp %s for %s",tname,collname);
  920.     fprintf (scanF,"V%d\n",SCANVERSION);
  921.     (void) Tprocess (listT,recordone,scanF);
  922.     (void) fclose (scanF);
  923.     if (rename (tname,fname) < 0)
  924.         goaway ("Can't change %s to %s",tname,fname);
  925.     (void) unlink (tname);
  926. #ifdef _ABI_SOURCE
  927.     tbuf.actime = time((time_t *)NULL);
  928.     tbuf.modtime = scantime;
  929.     (void) utime (fname,&tbuf);
  930. #else
  931.     tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  932.     tbuf[1].tv_sec = scantime;  tbuf[1].tv_usec = 0;
  933.     (void) utimes (fname,tbuf);
  934. #endif
  935. }
  936.  
  937. static
  938. recordone (t,scanF)
  939. TREE *t;
  940. FILE **scanF;
  941. {
  942.     int recordexec ();
  943.  
  944.     if (t->Tflags&FBACKUP)  fprintf (*scanF,"B");
  945.     if (t->Tflags&FNOACCT)  fprintf (*scanF,"N");
  946.     fprintf (*scanF,"%o %d %d %s\n",
  947.         t->Tmode,t->Tctime,t->Tmtime,t->Tname);
  948.     (void) Tprocess (t->Texec,recordexec,*scanF);
  949.     return (SCMOK);
  950. }
  951.  
  952. static
  953. recordexec (t,scanF)
  954. TREE *t;
  955. FILE **scanF;
  956. {
  957.     fprintf(*scanF,"X%s\n",t->Tname);
  958.     return (SCMOK);
  959. }
  960.  
  961. cdprefix (prefix)
  962. char *prefix;
  963. {
  964.     static char *curprefix = NULL;
  965.  
  966.     if (curprefix == NULL) {
  967.         if (prefix == NULL)
  968.             return;
  969.         (void) chdir (prefix);
  970.         curprefix = prefix;
  971.         return;
  972.     }
  973.     if (prefix == NULL) {
  974.         (void) chdir (basedir);
  975.         curprefix = NULL;
  976.         return;
  977.     }
  978.     if (prefix == curprefix)
  979.         return;
  980.     if (strcmp (prefix, curprefix) == 0) {
  981.         curprefix = prefix;
  982.         return;
  983.     }
  984.     (void) chdir (basedir);
  985.     (void) chdir (prefix);
  986.     curprefix = prefix;
  987. }
  988.